<template>
  <div class="goods-sku">
    <dl v-for="item in specs" :key="item.name">
      <dt>{{ item.name }}</dt>
      <!-- 图片 -->
      <dd v-if="item.values[0].picture">
        <img
          :class="{ selected: item2.select, disabled: item2.disabled }"
          v-src="item2.picture"
          alt=""
          v-for="item2 in item.values"
          :key="item2.name"
          @click="handleChoose(item2, item)"
        />
      </dd>
      <!-- 规格 -->
      <dd v-else>
        <span
          :class="{ selected: item2.select, disabled: item2.disabled }"
          :disabled="item2.disabled"
          v-for="item2 in item.values"
          :key="item2.name"
          @click="handleChoose(item2, item)"
        >
          {{ item2.name }}
        </span>
      </dd>
    </dl>
  </div>
</template>
<script>
import bwPowerSet from '@/vender/power-set'
// const aaa = bwPowerSet(['韩信', '李白', 888, 288, 1688])
// console.log(aaa)

export default {
  name: 'GoodsSku',
  props: ['specs', 'skus', 'skuId'],
  setup (props) {
    const handleChoose = (theItem, parentItem) => {
      if (theItem.disabled) return // 禁用
      // 排他
      if (!theItem.select) {
        parentItem.values.map(items => (items.select = false))
      }
      // 切换状态
      theItem.select = !theItem.select
      // 禁用状态
      updateDisabledStatus(props.specs, pathMap)
    }

    const getPathMap = arr => {
      const pathMap = {}
      arr.map(sku => {
        if (!sku.inventory) return false // 排除所有无库存
        const arr = sku.specs.map(item2 => item2.valueName)
        // console.log(arr)
        const powerSet = bwPowerSet(arr) // 计算出所有可能的幂集组合
        // console.log(powerSet)
        powerSet.map(keys => {
          const str = keys.join('&&') // 生成键名
          // console.log(str)
          if (!pathMap[str]) pathMap[str] = [sku.id] // 创建键值
          if (pathMap[str]) pathMap[str].push(sku.id) // 追加键值
        })
      })
      return pathMap
    }

    // 幂集字典
    const pathMap = getPathMap(props.skus)
    // console.log(pathMap)

    // 得到当前选中规格集合
    const getSelectedArr = specs => {
      // console.log(specs)
      const selectedArr = []
      specs.map(spec => {
        const selectedVal = spec.values.find(val => val.select) // 找出选中的 spec
        // console.log(selectedVal)
        selectedArr.push((selectedVal && selectedVal.name) || undefined)
      })

      return selectedArr
    }

    // 更新按钮的禁用状态
    const updateDisabledStatus = (specs, pathMap) => {
      /**
       * specs - 对象数组
       * pathMap - 字典
       */
      specs.map((spec, index) => {
        const selectedArr = getSelectedArr(specs) // 已选中的数组
        // console.log(selectedArr)
        spec.values.map(val => {
          // console.log(selectedArr[index], index)
          // console.log(val.name)
          if (val.name === selectedArr[index]) return false // 已经选中的按钮不用判断
          // 未选中的替换对应的值
          selectedArr[index] = val.name
          // console.log(selectedArr)
          // 过滤无效字段 - 找出所有的可能性
          const key = selectedArr.filter(v => v).join('&&')
          // console.log(key)
          val.disabled = !pathMap[key] // 设置禁用状态
          // if (!pathMap[key]) console.log(key, pathMap[key])
          // console.log(val.name, val.disabled)
        })
      })
      /**
       * ! 文字逻辑描述
       * specs - 规格数组：[颜色, 产地, 长度]，长度为三，index为0,1,2
       * spec - 对应规格的属性值数组：'颜色' - [黑色，蓝色]；'产地' - [日本，中国]
       * selectedArr - 已选规格的集合数组，对应[颜色, 产地, 长度]，未选的对应规格为undefined
       * 遍历三次这个规格数组，每次遍历的时候生成一个新的 selectedArr (防止污染)
       * 第一次遍历的时候只判断'颜色'规格，黑色或蓝色。
       * 假设选中的是黑色，跟'颜色'中的第一项相同，已经选了所以用户下一次不可能点它，返回false，退出 spec 的第一次遍历
       * 进入 spec 第二次遍历，val 是蓝色，是可能出现的操作，替换它，过滤undefined拼接成 key ，在字典中匹配 包含其他已选项的情况下是否允许出现'蓝色'这种规格，不存在则禁用蓝色
       *
       */

      /**
       * ? 失败尝试
       *  const mapKeysArr = Object.keys(pathMap)
      const selectedArr = getSelectedArr(specs) // 已选中的数组
      const arr = selectedArr.filter(i => i)
      console.log(arr)
      const maybe = []
      specs.map(spec => {
        spec.values.map(val => {
          // 找出零库存的规格
          const none = mapKeysArr.some(key => key.includes(val.name))
          if (!none) val.disabled = !none
          // console.log(val.name, none)
          // 没有任何选择，不预判
          if (!arr.length) return false
          // 至少选择一个，再开始预判
          // 根据 所选项 和 字典 匹配出所有允许出现的可能性
          const arr2 = mapKeysArr.filter(key =>
            arr.some(item => key.includes(item))
          )
          maybe.push(...arr2)
          // 格式处理
          const maybeArr = maybe
            .filter((item, index) => maybe.indexOf(item) === index) // 去重
            .join('&&')
            .split('&&')
          // console.log(maybeArr)
          const aabc = maybeArr.filter(
            (item, index) => maybeArr.indexOf(item) === index
          ) // 二次去重
          console.log(aabc)
          // aabc.map(key => {})
        })
      })
       */
    }
    updateDisabledStatus(props.specs, pathMap)
    // console.log(getSelectedArr(props.specs))

    // 初始化选中状态
    const initSelectedStatus = (skus, skuId, specs) => {
      const sku = skus.find(sku => sku.id === skuId) // 找出 id 对应的对象
      if (!sku) return false
      specs.map((spec, index) => {
        const value = sku.specs[index].valueName // 找出规格名
        spec.values.map(val => (val.select = val.name === value)) // 相同的规格名选中
      })
    }
    initSelectedStatus(props.skus, props.skuId, props.specs)

    return { handleChoose }
  }
}
</script>
<style scoped lang="less">
.sku-state-mixin () {
  border: 1px solid #e4e4e4;
  margin-right: 10px;
  cursor: pointer;
  &.selected {
    border-color: @xtxColor;
  }
  &.disabled {
    opacity: 0.6;
    border-style: dashed;
    cursor: not-allowed;
  }
}
.goods-sku {
  padding-left: 10px;
  padding-top: 20px;
  dl {
    display: flex;
    padding-bottom: 20px;
    align-items: center;
    dt {
      width: 50px;
      color: #999;
    }
    dd {
      flex: 1;
      color: #666;
      > img {
        width: 50px;
        height: 50px;
        .sku-state-mixin ();
      }
      > span {
        display: inline-block;
        height: 30px;
        line-height: 28px;
        padding: 0 20px;
        .sku-state-mixin ();
      }
    }
  }
}
</style>
